package com.ysjy.course.utils;

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.wkbb.common.constants.ErrorCode;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.handler.JsonUtil;
import com.ysjy.CourseApplication;
import com.ysjy.course.model.YsOrder;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

import static com.github.wxpay.sdk.WXPayUtil.MD5;

@Slf4j
public class WeChatPayUtil {

    public static final String mchID = "1626253754";
    public static final String mchKey = "1nbelHA6XbP3nX83lL4DEhieJQWbS8X2";
    public static String certPath = CourseApplication.applicationContext.getEnvironment().getProperty("wxpay.cert");
    public static String notifyUrl = CourseApplication.applicationContext.getEnvironment().getProperty("wxpay.notifyUrl");
    //时时练
//    public static final String appId = "wxfb9f17295963fe88";
//    public static final String secret = "876c70e30d694faf5c55ccb6b0c128cd";
    //因时体测
    public static final String appId = "wx6177c5b3e51c98e1";
    public static final String secret = "7ff0cdfbc0b90b9ee390bc10191cb6e3";


    public static WXPay wxpay = null;

    public static WXPay getWxpay(){
        if (wxpay == null){
            wxpay = new WXPay(new MyConfig());
        }
        return wxpay;
    }

    public static ResultDTO<String> pay(YsOrder order) {
        Map<String, String> data = new HashMap<String, String>();
        data.put("trade_type", "JSAPI");
        if (order.getOpenId() == null) {
            System.out.println("微信小程序支付。openId不能为空");
            return null;
        }
        data.put("spbill_create_ip", getLocalIP());
        data.put("body", order.getTitle());
        data.put("openid", order.getOpenId());
        data.put("out_trade_no", order.getOrderNumber());
//        data.put("device_info", "");
        int totalFee = order.getAmount();
        data.put("total_fee", String.valueOf(totalFee));
        data.put("notify_url", notifyUrl);
        try {
//            payConfTO.setMchCert("C:/data/cert/apiclient_cert.p12");
            Map<String, String> resp = getWxpay().unifiedOrder(data);
            log.info("支付信息：" + resp.toString());
            if ("SUCCESS".equals(resp.get("result_code"))) {
                JSONObject jsonObject = new JSONObject();
                String timeStamp = String.valueOf(System.currentTimeMillis()/1000);
                //小程序支付
                String nonceStr = WXPayUtil.generateNonceStr();
                String packages = "prepay_id=" + resp.get("prepay_id");
//                String weixin_sign2 = "appId=" + appId + "&" + "nonceStr=" + nonceStr + "&package=" + packages + "&" + "timeStamp=" + timeStamp;
//                String signTemp = weixin_sign2 + "&key=" + mchKey;
//                log.info("signTemp:{}",signTemp);
//                String paySign = WXPayUtil.HMACSHA256(signTemp,mchKey);

                String signType = "MD5";
                Map<String, String> signTemp = new HashMap<>();
                signTemp.put("appId", appId);
                signTemp.put("nonceStr", nonceStr);
                signTemp.put("package", packages);
                signTemp.put("signType", signType);
                signTemp.put("timeStamp", timeStamp);
                String paySign = WXPayUtil.generateSignature(signTemp,mchKey,WXPayConstants.SignType.MD5);

                jsonObject.put("appId", appId);
                jsonObject.put("timeStamp", timeStamp);
                jsonObject.put("nonceStr", nonceStr);
                jsonObject.put("package", packages);
                jsonObject.put("signType", signType);
                jsonObject.put("paySign", paySign);
                return ResultDTO.successResult(jsonObject.toJSONString());
            }
            return ResultDTO.errorResult(resp.get("err_code_des"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 特殊字符处理
    public static String UrlEncode(String src) throws UnsupportedEncodingException {
        return URLEncoder.encode(src, "UTF-8").replace("+", "%20");
    }

    public static ResultDTO<Boolean> refund(YsOrder order) {
        TreeMap<String, String> data = new TreeMap<String, String>();
        data.put("transaction_id", "");
        data.put("out_trade_no", order.getOrderNumber());
        data.put("out_refund_no", order.getRefundNumber());
        data.put("total_fee", String.valueOf(order.getAmount()));
        data.put("refund_fee", String.valueOf(order.getRefundAmount()));
        try {
            log.info("refund:"+ JsonUtil.objectToJson(data));
            Map<String, String> resp = getWxpay().refund(data);
            log.info("退款结果：" + resp);
            if ("SUCCESS".equals(resp.get("result_code"))) {
                return new ResultDTO<>();
            }
            return ResultDTO.errorResult(resp.get("err_code_des"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ResultDTO<>(ErrorCode.SYSTEM_ERROR);
    }

    static class MyConfig implements WXPayConfig {
        private byte[] certData;

        public MyConfig() {
            log.info("certPath:"+certPath);
            File file = new File(certPath);
            try {
                InputStream certStream = new FileInputStream(file);
                this.certData = new byte[(int) file.length()];
                certStream.read(this.certData);
                certStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public String getAppID() {
            return appId;
        }

        public String getMchID() {
            return mchID;
        }

        public String getKey() {
            return mchKey;
        }

        public InputStream getCertStream() {
            ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
            return certBis;
        }

        public int getHttpConnectTimeoutMs() {
            return 8000;
        }

        public int getHttpReadTimeoutMs() {
            return 10000;
        }
    }

    /**
     * 产生大写字母和数字的随机数
     *
     * @param length
     * @return
     */
    public static String getRandomStringByLength(int length) {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 获取本地IP
     *
     * @return
     */
    public static String getLocalIP() {
        InetAddress addr = null;
        try {
            addr = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        byte[] ipAddr = addr.getAddress();
        String ipAddrStr = "";
        for (int i = 0; i < ipAddr.length; i++) {
            if (i > 0) {
                ipAddrStr += ".";
            }
            ipAddrStr += ipAddr[i] & 0xFF;
        }
        return ipAddrStr;
    }


    public static void main(String[] args) {
        Map<String, String> resp = new HashMap<>();
        resp.put("result_code", "SUCCESS");
        resp.put("err_code", "NOTENOUGH");
        System.out.println(resp.containsKey("err_code"));
        if ("SUCCESS".equals(resp.get("result_code")) && !resp.containsKey("err_code")) {
            System.out.println("成功！");
        } else {
            System.out.println("失败！");
        }
        if (resp.containsKey("err_code") && "NOTENOUGH".equals(resp.get("err_code"))) {
            //商户余额不足
            System.out.println("商户余额不足！");
        }
    }
}
